/**
 * <pre>
 * @(#)LayoutView.java 1.00 2009-11-4
 * 
 * Copyright (c) 1998, 2009 Regular Individual. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Contributor(s):
 *     Haixu Huang
 * </pre>
 **/
package cn.sh.huang.chart.view.container;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import cn.sh.huang.chart.config.TitleConfig;
import cn.sh.huang.chart.ext.ChartUtilities;
import cn.sh.huang.chart.ext.enumtype.Direction;
import cn.sh.huang.chart.ext.enumtype.Extension;
import cn.sh.huang.chart.ext.enumtype.Position;
import cn.sh.huang.chart.ext.enumtype.Side;
import cn.sh.huang.chart.view.AbstractView;
import cn.sh.huang.chart.view.SideView;
import cn.sh.huang.chart.view.TitleView;
import cn.sh.huang.chart.view.View;

/**
 * <pre>
 * LayoutView ...
 * 
 * @version 1.0
 * </pre>
 */
public class LayoutView extends ViewContainer
{
    private static final Color DEFAULT_CHART_BGCOLOR = new Color(0xF0, 0xF0, 0xF0);
    private AbstractView titleView, subTitleView, legendView, contentView;
    private final Rectangle titleRect = new Rectangle(), subTitleRect = new Rectangle(), legendRect = new Rectangle(),
            contentRect = new Rectangle();

    public LayoutView()
    {
        setBgColor(DEFAULT_CHART_BGCOLOR);
    }

    private Dimension getLayoutViewSize(boolean isPreferred)
    {
        Dimension size =
            (contentView != null) ? (isPreferred ? contentView.getPreferredSize() : contentView.getMinimumSize())
                : new Dimension(0, 0);
        if (legendView != null) {
            getSideViewSize((SideView) legendView, size, isPreferred);
        }
        if (subTitleView != null) {
            getSideViewSize((SideView) subTitleView, size, isPreferred);
        }
        if (titleView != null) {
            getSideViewSize((SideView) titleView, size, isPreferred);
        }
        return size;
    }

    public Dimension getPreferredSize()
    {
        return getLayoutViewSize(true);
    }

    public Dimension getMinimumSize()
    {
        return getLayoutViewSize(false);
    }

    public void render(Graphics2D g2d)
    {
        if (titleView != null) {
            titleView.render(g2d);
        }
        if (subTitleView != null) {
            subTitleView.render(g2d);
        }
        if (legendView != null) {
            legendView.render(g2d);
        }
        if (contentView != null) {
            contentView.render(g2d);
        }
    }

    public void setViewSize(final int width, final int height)
    {
        Rectangle _rect = new Rectangle(0, 0, width, height);
        if (titleView != null) {
            setSideViewRect((SideView) titleView, _rect, titleRect);
        }
        if (subTitleView != null) {
            setSideViewRect((SideView) subTitleView, _rect, subTitleRect);
        }
        if (legendView != null) {
            setSideViewRect((SideView) legendView, _rect, legendRect);
        }
        if (contentView != null) {
            contentRect.setRect(_rect);
            contentView.setViewSize(_rect.width, _rect.height);
        }
        super.setViewSize(width, height);
    }

    private void setSideViewRect(SideView view, Rectangle rect, Rectangle viewRect)
    {
        Dimension size = ChartUtilities.fitRect(rect, view.getPreferredSize());
        int x = rect.x + (rect.width - size.width) / 2, y = rect.y + (rect.height - size.height) / 2;
        Position p = view.getPosition();
        if (p.onTheSide(Side.LEFT)) {
            x = rect.x;
        } else if (p.onTheSide(Side.RIGHT)) {
            x = rect.x + rect.width - size.width;
        }
        if (p.onTheSide(Side.TOP)) {
            y = rect.y;
        } else if (p.onTheSide(Side.BOTTOM)) {
            y = rect.y + rect.height - size.height;
        }
        viewRect.setRect(x, y, size.width, size.height);
        view.setViewSize(size.width, size.height);
        Direction d = view.getDirection();
        Extension e = view.getExtension();
        if ((p.onTheSide(Side.TOP) || p.onTheSide(Side.BOTTOM))
            && ((d.northOrSouth() && e.equals(Extension.TANGENT)) || (d.westOrEast() && e.equals(Extension.NORMAL)))) {
            rect.height -= size.height;
            if (p.onTheSide(Side.TOP)) {
                rect.y += size.height;
            }
        } else if ((p.onTheSide(Side.LEFT) || p.onTheSide(Side.RIGHT))
            && ((d.westOrEast() && e.equals(Extension.TANGENT)) || (d.northOrSouth() && e.equals(Extension.NORMAL)))) {
            rect.width -= size.width;
            if (p.onTheSide(Side.LEFT)) {
                rect.x += size.width;
            }
        }
    }

    private Dimension getSideViewSize(SideView view, Dimension size, boolean isPreferred)
    {
        Dimension dd = isPreferred ? view.getPreferredSize() : view.getMinimumSize();
        Position p = view.getPosition();
        Direction d = view.getDirection();
        Extension e = view.getExtension();
        if ((p.onTheSide(Side.TOP) || p.onTheSide(Side.BOTTOM))
            && ((d.northOrSouth() && e.equals(Extension.TANGENT)) || (d.westOrEast() && e.equals(Extension.NORMAL)))) {
            size.height += dd.height;
            size.width = Math.max(size.width, dd.width);
        } else if ((p.onTheSide(Side.LEFT) || p.onTheSide(Side.RIGHT))
            && ((d.westOrEast() && e.equals(Extension.TANGENT)) || (d.northOrSouth() && e.equals(Extension.NORMAL)))) {
            size.width += dd.width;
            size.height = Math.max(size.height, dd.height);
        }
        return size;
    }

    private TitleView getTitleView()
    {
        if (titleView == null) {
            titleView = new TitleView(null);
            titleView.setViewContainer(this);
        }
        return (TitleView) titleView;
    }

    public void setTitle(String title)
    {
        getTitleView().setText(title);
    }

    public TitleConfig getTitleConfig()
    {
        return getTitleView().getConfig();
    }

    private TitleView getSubTitleView()
    {
        if (subTitleView == null) {
            subTitleView = new TitleView(null);
            subTitleView.setViewContainer(this);
        }
        return (TitleView) subTitleView;
    }

    public void setSubTitle(String subTitle)
    {
        getSubTitleView().setText(subTitle);
    }

    public TitleConfig getSubTitleConfig()
    {
        return getSubTitleView().getConfig();
    }

    public void setContent(View contentView)
    {
        if (this.contentView == contentView) {
            return;
        }
        if (this.contentView != null) {
            this.contentView.dispose();
        }
        contentView.setViewContainer(this);
        this.contentView = contentView;
    }

    /*
     * (non-Javadoc)
     * @see cn.sh.huang.chart.view.container.ViewContainer#getSubViewRect(cn.sh.huang.chart.view.AbstractView)
     */
    public Rectangle getGridRect(AbstractView view)
    {
        if (view.equals(titleView)) {
            return (Rectangle) titleRect.clone();
        }
        if (view.equals(subTitleView)) {
            return (Rectangle) subTitleRect.clone();
        }
        if (view.equals(legendView)) {
            return (Rectangle) legendRect.clone();
        }
        if (view.equals(contentView)) {
            return (Rectangle) contentRect.clone();
        }
        return null;
    }
}
